
package com.bangcommunity.bbframe.sdm.web.shiro.token;

import com.bangcommunity.bbframe.common.base.BaseResult;
import com.bangcommunity.bbframe.common.base.ResultCode;
import com.bangcommunity.bbframe.common.exception.ValidateUtil;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.subject.Subject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;

/**
 * 根据token进行认证 基于Shiro 实现的SSO登陆认证的Filter 用于拦截所有需要登录状态访问的url以及判断登录请求执行登录。
 * 1、此处判断是否登录状态除了默认的shiro中的session判断外,增加了对session中存储的uid和token的校验。 从而保证token失效之后,登录状态失效。
 * token&uid的校验根据子应用实现 2、判断登录请求使用shiro默认判断login url,或者是参数(url、header、cookie)中包含SSO_TOKEN参数。
 * 3、获取SSO_TOKEN并使用该token构建登录信息供shiro执行登录。子类扩展需要构造的登录信息。
 * 4、子应用需要配置app.session.login.expire.ms用于控制登录状态的过期时间。-1表示永不过期。
 *
 * @version 1.0
 * @author tanghc
 */
public abstract class AbstractTokenAuthFilter extends AbstractTokenAuthenticationFilter {

    protected Logger logger = LoggerFactory.getLogger(this.getClass());

    @Override
    protected boolean onLoginSuccess(AuthenticationToken token, Subject subject, ServletRequest request,
            ServletResponse response) throws Exception {
        String resourceId = getResourceId(request, response);
        try {
            boolean pass = hasPermition(request, response, resourceId);
            if(pass){
                return onPermit(request, response);
            }
            ValidateUtil.isTrue(pass, "没有权限访问");
            return pass;
        } catch (Exception e) {
            return onForbbiden(request,response,e);
        }
    }
    protected abstract boolean hasPermition(ServletRequest request,
                                            ServletResponse response,String resourceId) throws Exception;

    protected abstract String getResourceId( ServletRequest request,
                                             ServletResponse response) ;

    protected boolean onPermit( ServletRequest request,
                                ServletResponse response) throws Exception {
        return true;
    }

    protected boolean onForbbiden( ServletRequest req,
                                   ServletResponse res,Exception exception) {
        return doFailResponse(null,exception,req,res,isForceRest(),BaseResult.fail(ResultCode.NOTALLOWED.getCode(), "没有权限访问"));
    }




}
